package com.afc.struts.form.generator;

import org.objectweb.asm.Opcodes;

public class AsmUtils
{
  static public final String getClassSimpleName(String aClassName)
  {
    int startIndex = 0;
    int lastIndex = Math.max(aClassName.lastIndexOf("/"), aClassName.lastIndexOf("$"));
    if (lastIndex >= 0)
    {
      startIndex = lastIndex + 1;
    }
    return aClassName.substring(startIndex);
  }

  static public String getReferenceName(String aClassName)
  {
    if (aClassName.equals(Integer.TYPE.getName()))
    {
      return TypeDescription.INT + "";
    }
    else if (aClassName.equals(Short.TYPE.getName()))
    {
      return TypeDescription.SHORT + "";
    }
    else if (aClassName.equals(Long.TYPE.getName()))
    {
      return TypeDescription.LONG + "";
    }
    else if (aClassName.equals(Double.TYPE.getName()))
    {
      return TypeDescription.DOUBLE + "";
    }
    else if (aClassName.equals(Float.TYPE.getName()))
    {
      return TypeDescription.FLOAT + "";
    }
    else if (aClassName.equals(Character.TYPE.getName()))
    {
      return TypeDescription.CHAR + "";
    }
    else if (aClassName.equals(Boolean.TYPE.getName()))
    {
      return TypeDescription.BOOLEAN + "";
    }
    return "L" + aClassName + ";";
  }

  static public int getLoadOpcode(String aClassName)
  {
    if (aClassName.equals(Integer.TYPE.getName()))
    {
      return Opcodes.ILOAD;
    }
    else if (aClassName.equals(Short.TYPE.getName()))
    {
      return Opcodes.ILOAD;
    }
    else if (aClassName.equals(Long.TYPE.getName()))
    {
      return Opcodes.LLOAD;
    }
    else if (aClassName.equals(Double.TYPE.getName()))
    {
      return Opcodes.DLOAD;
    }
    else if (aClassName.equals(Float.TYPE.getName()))
    {
      return Opcodes.FLOAD;
    }
    else if (aClassName.equals(Character.TYPE.getName()))
    {
      return Opcodes.ILOAD;
    }
    else if (aClassName.equals(Boolean.TYPE.getName()))
    {
      return Opcodes.ILOAD;
    }
    return Opcodes.ALOAD;
  }

  static public int getReturnOpcode(String aClassName)
  {
    if (aClassName.equals(Integer.TYPE.getName()))
    {
      return Opcodes.IRETURN;
    }
    else if (aClassName.equals(Short.TYPE.getName()))
    {
      return Opcodes.IRETURN;
    }
    else if (aClassName.equals(Long.TYPE.getName()))
    {
      return Opcodes.LRETURN;
    }
    else if (aClassName.equals(Double.TYPE.getName()))
    {
      return Opcodes.DRETURN;
    }
    else if (aClassName.equals(Float.TYPE.getName()))
    {
      return Opcodes.FRETURN;
    }
    else if (aClassName.equals(Character.TYPE.getName()))
    {
      return Opcodes.IRETURN;
    }
    else if (aClassName.equals(Boolean.TYPE.getName()))
    {
      return Opcodes.IRETURN;
    }
    return Opcodes.ARETURN;
  }

  static public String fromHighLevelClassName(String aHighLevelClassName)
  {
    return aHighLevelClassName.replace(".", "/");
  }

  static public String toHighLevelClassName(String aClassName)
  {
    return aClassName.replace("/", ".");
  }

  static public final String CONSTRUCTOR_NAME = "<init>";
  static public final String OBJECT_CONSTRUCTOR_DESCRIPTION = "()V";

  static public final String STATIC_INITIALIZER_NAME = "<clinit>";
  static public final String STATIC_INITIALIZER_DESCRIPTION = "()V";

  static public final String OUTER_FIELD_NAME = "this$0";

  static public final String PRIMITIVE_CLASS_ATTRIBUTE_NAME = "TYPE";
  static public final String UNPRIMITIVE_CONVERTER_NAME = "valueOf";

  static public final String PRIMITIVE_INTEGER_CONVERTER_NAME = "intValue";
  static public final String PRIMITIVE_INTEGER_CONVERTER_DESCRIPTION = "()" + TypeDescription.INT;

  static public final String PRIMITIVE_BYTE_CONVERTER_NAME = "byteValue";
  static public final String PRIMITIVE_BYTE_CONVERTER_DESCRIPTION = "()" + TypeDescription.BYTE;

  static public final String PRIMITIVE_CHAR_CONVERTER_NAME = "charValue";
  static public final String PRIMITIVE_CHAR_CONVERTER_DESCRIPTION = "()" + TypeDescription.CHAR;

  static public final String PRIMITIVE_DOUBLE_CONVERTER_NAME = "doubleValue";
  static public final String PRIMITIVE_DOUBLE_CONVERTER_DESCRIPTION = "()" + TypeDescription.DOUBLE;

  static public final String PRIMITIVE_FLOAT_CONVERTER_NAME = "floatValue";
  static public final String PRIMITIVE_FLOAT_CONVERTER_DESCRIPTION = "()" + TypeDescription.FLOAT;

  static public final String PRIMITIVE_LONG_CONVERTER_NAME = "longValue";
  static public final String PRIMITIVE_LONG_CONVERTER_DESCRIPTION = "()" + TypeDescription.LONG;

  static public final String PRIMITIVE_SHORT_CONVERTER_NAME = "shortValue";
  static public final String PRIMITIVE_SHORT_CONVERTER_DESCRIPTION = "()" + TypeDescription.SHORT;

  static public final String PRIMITIVE_BOOLEAN_CONVERTER_NAME = "booleanValue";
  static public final String PRIMITIVE_BOOLEAN_CONVERTER_DESCRIPTION = "()" + TypeDescription.BOOLEAN;

  static public final String INTEGER_CLASS_NAME = fromHighLevelClassName(Integer.class.getName());
  static public final String INTEGER_REFERENCE_NAME = getReferenceName(INTEGER_CLASS_NAME);
  static public final String INTEGER_CONVERTER_DESCRIPTION = "(" + TypeDescription.INT + ")" + INTEGER_REFERENCE_NAME;

  static public final String BYTE_CLASS_NAME = fromHighLevelClassName(Byte.class.getName());
  static public final String BYTE_REFERENCE_NAME = getReferenceName(BYTE_CLASS_NAME);
  static public final String BYTE_CONVERTER_DESCRIPTION = "(" + TypeDescription.BYTE + ")" + BYTE_REFERENCE_NAME;

  static public final String CHARACTER_CLASS_NAME = fromHighLevelClassName(Character.class.getName());
  static public final String CHARACTER_REFERENCE_NAME = getReferenceName(CHARACTER_CLASS_NAME);
  static public final String CHARACTER_CONVERTER_DESCRIPTION = "(" + TypeDescription.CHAR + ")" + CHARACTER_REFERENCE_NAME;

  static public final String DOUBLE_CLASS_NAME = fromHighLevelClassName(Double.class.getName());
  static public final String DOUBLE_REFERENCE_NAME = getReferenceName(DOUBLE_CLASS_NAME);
  static public final String DOUBLE_CONVERTER_DESCRIPTION = "(" + TypeDescription.DOUBLE + ")" + DOUBLE_REFERENCE_NAME;

  static public final String FLOAT_CLASS_NAME = fromHighLevelClassName(Float.class.getName());
  static public final String FLOAT_REFERENCE_NAME = getReferenceName(FLOAT_CLASS_NAME);
  static public final String FLOAT_CONVERTER_DESCRIPTION = "(" + TypeDescription.FLOAT + ")" + FLOAT_REFERENCE_NAME;

  static public final String LONG_CLASS_NAME = fromHighLevelClassName(Long.class.getName());
  static public final String LONG_REFERENCE_NAME = getReferenceName(LONG_CLASS_NAME);
  static public final String LONG_CONVERTER_DESCRIPTION = "(" + TypeDescription.LONG + ")" + LONG_REFERENCE_NAME;

  static public final String SHORT_CLASS_NAME = fromHighLevelClassName(Short.class.getName());
  static public final String SHORT_REFERENCE_NAME = getReferenceName(SHORT_CLASS_NAME);
  static public final String SHORT_CONVERTER_DESCRIPTION = "(" + TypeDescription.SHORT + ")" + SHORT_REFERENCE_NAME;

  static public final String BOOLEAN_CLASS_NAME = fromHighLevelClassName(Boolean.class.getName());
  static public final String BOOLEAN_REFERENCE_NAME = getReferenceName(BOOLEAN_CLASS_NAME);
  static public final String BOOLEAN_CONVERTER_DESCRIPTION = "(" + TypeDescription.BOOLEAN + ")" + BOOLEAN_REFERENCE_NAME;

  static public final String STRING_CLASS_NAME = fromHighLevelClassName(String.class.getName());
  static public final String STRING_REFERENCE_NAME = getReferenceName(STRING_CLASS_NAME);

  static public final String CLASS_CLASS_NAME = fromHighLevelClassName(Class.class.getName());
  static public final String CLASS_REFERENCE_NAME = getReferenceName(CLASS_CLASS_NAME);

  static public final String VOID_CLASS_NAME = fromHighLevelClassName(Void.class.getName());
  static public final String VOID_REFERENCE_NAME = getReferenceName(VOID_CLASS_NAME);

  static public final String OBJECT_CLASS_NAME = fromHighLevelClassName(Object.class.getName());
  static public final String OBJECT_REFERENCE_NAME = getReferenceName(OBJECT_CLASS_NAME);

  static public final String THROWABLE_CLASS_NAME = fromHighLevelClassName(Throwable.class.getName());
  static public final String THROWABLE_REFERENCE_NAME = getReferenceName(THROWABLE_CLASS_NAME);

  static public final String EXCEPTION_CLASS_NAME = fromHighLevelClassName(Exception.class.getName());
  static public final String EXCEPTION_REFERENCE_NAME = getReferenceName(EXCEPTION_CLASS_NAME);

  static public final String ERROR_CLASS_NAME = fromHighLevelClassName(Error.class.getName());
  static public final String ERROR_REFERENCE_NAME = getReferenceName(ERROR_CLASS_NAME);

  static public final String RUNTIME_EXCEPTION_CLASS_NAME = fromHighLevelClassName(RuntimeException.class.getName());
  static public final String RUNTIME_EXCEPTION_REFERENCE_NAME = getReferenceName(RUNTIME_EXCEPTION_CLASS_NAME);

  static public final String BYTE_ARRAY_CLASS_NAME = fromHighLevelClassName(byte[].class.getName());
}
